import matplotlib
# 设置matplotlib使用TkAgg后端（你也可以尝试QtAgg等其他后端，需确保对应依赖已安装）
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

# 设置字体为黑体，用于解决中文显示问题（适用于Windows系统，Linux和macOS可按需调整字体）
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决负号显示异常问题
plt.rcParams['axes.unicode_minus'] = False

# 步骤1：加载数据
# 定义数据的URL，这里是UCI机器学习数据库中白酒数据的链接
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data"
# 定义数据的列名，分别对应不同的属性和类别标签
columns = ['Class', 'Alcohol', 'Malic_acid', 'Ash', 'Alcalinity_of_ash', 'Magnesium',
           'Total_phenols', 'Flavanoids', 'Nonflavanoid_phenols', 'Proanthocyanins',
           'Color_intensity', 'Hue', 'OD280/OD315', 'Proline']
# 使用pandas的read_csv函数读取数据，设置header=None表示数据文件中无表头，names参数指定列名
data = pd.read_csv(url, header=None, names=columns)

# 步骤2：筛选类别1和类别2的数据
# 通过条件筛选，选取数据中类别标签为1或者2的数据子集，isin函数用于判断是否在给定的列表中
filtered_data = data[data['Class'].isin([1, 2])]
# 提取筛选后数据的特征部分，即除了第一列（类别标签列）以外的所有列作为特征数据
X = filtered_data.iloc[:, 1:]
# 提取筛选后数据的类别标签列作为标签数据，后续LDA降维会用到标签信息
y = filtered_data['Class']

# 步骤3：PCA - 降维到二维
# 创建PCA对象，设置要降维到的主成分数量为2，即把原始的多维数据降维到二维空间
pca = PCA(n_components=2)
# 使用fit_transform方法对特征数据X进行拟合和转换，得到降维后的二维数据
X_pca = pca.fit_transform(X)
# 打印提示信息
print("PCA降维后的二维特征：")
# 输出降维后的二维特征数据，方便查看具体的数据内容
print(X_pca)

# 步骤4：LDA - 降维到一维
# 创建LDA对象，对于只有两类的分类问题，LDA降维后维度通常为1，这里设置n_components=1
lda = LDA(n_components=1)
# 使用fit_transform方法对特征数据X和对应的标签数据y进行拟合和转换，得到降维后的一维数据
X_lda = lda.fit_transform(X, y)
# 打印提示信息
print("LDA降维后的一维特征：")
# 输出降维后的一维特征数据
print(X_lda)

# 步骤5：数据可视化
# PCA可视化
# 创建一个新的图形，设置图形的大小，figsize参数指定宽度和高度（单位为英寸）
plt.figure(figsize=(8, 6))
# 使用scatter函数绘制散点图，X_pca[:, 0]表示降维后二维数据的第一个维度（主成分1），
# X_pca[:, 1]表示第二个维度（主成分2），c=y表示根据类别标签y来给散点赋予不同的颜色，
# cmap='viridis'指定颜色映射方案，edgecolor='k'设置散点边缘颜色为黑色，s=50设置散点大小为50
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis', edgecolor='k', s=50)
# 设置图形的标题，说明这是PCA降维到二维后的散点图展示
plt.title('PCA: 降维到二维的散点图')
# 设置x轴的标签，表明是主成分1
plt.xlabel('主成分1')
# 设置y轴的标签，表明是主成分2
plt.ylabel('主成分2')
# 添加颜色条，用于显示不同颜色对应的类别标签信息，label参数设置颜色条的标题
plt.colorbar(label='类别标签')
# 显示网格线，使图形更加清晰易读
plt.grid()
# 显示绘制好的图形
plt.show()

# LDA可视化
# 创建一个新的图形，设置合适的大小
plt.figure(figsize=(8, 3))
# 绘制散点图，由于LDA降维后是一维数据，这里将所有散点的y坐标设置为0，形成在x轴上的散点分布，
# 同样根据类别标签y来给散点赋予颜色，其他参数设置与PCA可视化类似
plt.scatter(X_lda, [0] * len(X_lda), c=y, cmap='viridis', edgecolor='k', s=50)
# 设置图形的标题，表明这是LDA降维到一维后的散点图展示
plt.title('LDA: 降维到一维的散点图')
# 设置x轴的标签，说明是线性判别1
plt.xlabel('线性判别1')
# 移除y轴的刻度，使图形更加简洁清晰，因为在一维可视化中y轴实际无意义
plt.yticks([])
# 添加颜色条，用于显示类别标签信息
plt.colorbar(label='类别标签')
# 显示网格线
plt.grid()
# 显示绘制好的图形
plt.show()